package com.xjrsoft.common.utils;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.Enum.DeleteMarkEnum;
import com.xjrsoft.core.secure.utils.SecureUtil;
import com.xjrsoft.core.tool.utils.SpringUtil;
import com.xjrsoft.core.tool.utils.StringUtil;
import com.xjrsoft.module.base.entity.XjrBaseUser;
import com.xjrsoft.module.base.service.IXjrBaseUserRelationService;
import com.xjrsoft.module.oa.entity.XjrOaMessage;
import com.xjrsoft.module.oa.entity.XjrOaMessagestatus;
import com.xjrsoft.module.oa.service.IXjrOaMessageService;
import com.xjrsoft.module.oa.service.IXjrOaMessagestatusService;
import com.xjrsoft.module.oa.utils.SendMessageUtil;
import com.xjrsoft.module.workflow.entity.XjrNwfScheme;
import com.xjrsoft.module.workflow.entity.XjrNwfSchemeinfo;
import com.xjrsoft.module.workflow.mapper.NwfTaskMapper;
import com.xjrsoft.module.workflow.service.IXjrNwfSchemeInfoService;
import com.xjrsoft.module.workflow.service.IXjrNwfSchemeService;
import lombok.SneakyThrows;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TimerUtil {

    private final static TaskService taskService;

    private final static IXjrBaseUserRelationService userRelationService;


    private final static IXjrOaMessageService xjrOaMessageService;

    private final static IXjrOaMessagestatusService xjrOaMessagestatusService;

    private final static RuntimeService runtimeService;

    private final static RepositoryService repositoryService;

    private final static IXjrNwfSchemeInfoService nwfSchemeInfoService;

    private final static IXjrNwfSchemeService nwfSchemeService;

    private final static IXjrOaMessagestatusService iXjrOaMessagestatusService;

    private final static NwfTaskMapper nwfTaskMapper;

    static {
        userRelationService = SpringUtil.getBean(IXjrBaseUserRelationService.class);
        nwfTaskMapper = SpringUtil.getBean(NwfTaskMapper.class);
        runtimeService = SpringUtil.getBean(RuntimeService.class);
        taskService = SpringUtil.getBean(TaskService.class);
        xjrOaMessageService = SpringUtil.getBean(IXjrOaMessageService.class);
        xjrOaMessagestatusService = SpringUtil.getBean(IXjrOaMessagestatusService.class);
        repositoryService = SpringUtil.getBean(RepositoryService.class);
        nwfSchemeInfoService = SpringUtil.getBean(IXjrNwfSchemeInfoService.class);
        nwfSchemeService = SpringUtil.getBean(IXjrNwfSchemeService.class);
        iXjrOaMessagestatusService = SpringUtil.getBean(IXjrOaMessagestatusService.class);
    }

    public static void setOutTimeTimer() {
        String schedule = CronUtil.schedule("0 0/10 * * * ? ", new Task() {
            @SneakyThrows
            @Override
            public void execute() {
                Console.log("Task excuted.");
                //定时发送超时提醒·
                //获取该流程下所有当前正在运行的任务
                List<org.flowable.task.api.Task> list = taskService.createTaskQuery().list();
                for (org.flowable.task.api.Task task : list) {
                    if(!task.isSuspended()) {
                        if (StringUtil.isNotBlank(task.getProcessInstanceId())) {
                            String deploymentId = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getDeploymentId();
                            XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getByDeploymentId(deploymentId);
                            if (xjrNwfSchemeinfo != null) {
                                XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(xjrNwfSchemeinfo.getId());
                                if (xjrNwfScheme != null) {
                                    String fjson = xjrNwfScheme.getFjson();
                                    JSONObject obj = JSONObject.parseObject(fjson);
                                    JSONObject properties = obj.getJSONObject("properties");
                                    JSONObject timeoutToRemind = properties.getJSONObject("timeoutToRemind");
                                    if (timeoutToRemind != null) {
                                        String isOpen = timeoutToRemind.getString("isOpen");
                                        double timeOut = timeoutToRemind.getDouble("timeOut");
                                        double messageInterval = timeoutToRemind.getDouble("messageInterval");
                                        JSONArray jsonArray = timeoutToRemind.getJSONArray("messagePusherList");
                                        String pushTimes = timeoutToRemind.getString("pushTimes") == null ? "1" : timeoutToRemind.getString("pushTimes");
                                        if ("1".equals(isOpen)) {
                                            //开启超时提醒
                                            ArrayList<String> userids = nwfTaskMapper.getUserIdByTask(task.getId());
                                            if (jsonArray != null) {
                                                for (Object o : jsonArray) {
                                                    JSONObject jsonObject = (JSONObject) JSON.toJSON(o);
                                                    Integer t = Integer.valueOf(jsonObject.getString("F_ObjType"));
                                                    String fObjId = jsonObject.getString("F_ObjId");
                                                    switch (t) {
                                                        case 1:
                                                            // 岗位,把岗位下的用户设置成候选人
                                                            List<XjrBaseUser> usersOfPost = userRelationService.getUsersOfObject(fObjId, 2);
                                                            for (XjrBaseUser xjrBaseUser : usersOfPost) {
                                                                userids.add(xjrBaseUser.getUserId());
                                                            }
                                                            break;
                                                        case 2:
                                                            // 角色的限制条件
                                                            List<XjrBaseUser> usersOfRole = userRelationService.getUsersOfObject(fObjId, 1);
                                                            for (XjrBaseUser xjrBaseUser : usersOfRole) {
                                                                userids.add(xjrBaseUser.getUserId());
                                                            }
                                                            break;
                                                        case 3:
                                                            // 指定用户
                                                            JSONObject userInfo = new JSONObject();
                                                            userids.add(fObjId);
                                                            break;
                                                    }
                                                }
                                            }
                                            XjrOaMessage xjrOaMessage = xjrOaMessageService.getOne(Wrappers.<XjrOaMessage>query().lambda().eq(XjrOaMessage::getTaskId, task.getId()).eq(XjrOaMessage::getDeploymentId, deploymentId).eq(XjrOaMessage::getDeleteMark, DeleteMarkEnum.NODELETE.getCode()));
                                            if (xjrOaMessage == null) {
                                                //还未发送过一次超时提醒，判断是否超过超时时间
                                                long between = DateUtil.between(task.getCreateTime(), new Date(), DateUnit.MINUTE);
                                                //超过超时时间
                                                if (!((double)between<new BigDecimal(timeOut).multiply(new BigDecimal(60)).doubleValue())) {
                                                    ArrayList<Integer> messageSendType = new ArrayList<>();
                                                    messageSendType.add(10);
                                                    //给当前审批任务人和追加人发送提醒
                                                    SendMessageUtil.sendWorkFlowMessage(task, deploymentId, userids, 4, messageSendType);
                                                }
                                            } else {
                                                for (String userid : userids) {
                                                    List<XjrOaMessagestatus> xjrOaMessagestatusList = xjrOaMessagestatusService.list(Wrappers.<XjrOaMessagestatus>query().lambda().eq(XjrOaMessagestatus::getUserId, userid).eq(XjrOaMessagestatus::getMessageId, xjrOaMessage.getId()).eq(XjrOaMessagestatus::getDeleteMark, DeleteMarkEnum.NODELETE.getCode()).orderByDesc(XjrOaMessagestatus::getSendTime));
                                                    if ((xjrOaMessagestatusList != null && xjrOaMessagestatusList.size() < Integer.valueOf(pushTimes))) {
                                                        //未超过发送次数,获取最后一次发的时间
                                                        XjrOaMessagestatus xjrOaMessagestatus = xjrOaMessagestatusList.get(0);
                                                        long between = DateUtil.between(xjrOaMessagestatus.getSendTime(), new Date(), DateUnit.MINUTE);
                                                        //超过间隔时间
                                                        if (!((double)between<new BigDecimal(messageInterval).multiply(new BigDecimal(60)).doubleValue())) {
                                                            ArrayList<Integer> messageSendType = new ArrayList<>();
                                                            messageSendType.add(10);
                                                            //给当前审批任务人和追加人发送提醒
                                                            XjrOaMessagestatus xjrOaMessagestatus1 = new XjrOaMessagestatus();
                                                            xjrOaMessagestatus1.setMessageId(xjrOaMessage.getId()).setUserId(userid).setStatus(11).setSendTime(new Date())
                                                                    .setDeleteMark(DeleteMarkEnum.NODELETE.getCode()).setCreateDate(new Date()).setCreateUserId(SecureUtil.getUserId());
                                                            iXjrOaMessagestatusService.save(xjrOaMessagestatus1);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
        // 支持秒级别定时任务
        CronUtil.setMatchSecond(true);
        CronUtil.start();
    }
}
